package tableEmulater;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * @author Don
 *
 */
@SuppressWarnings("serial")
public class TableGUI extends JPanel implements MouseListener {
	/**
	 * Circle packing efficiency for use in aligning cups
	 */
	private static final double CIRCLE_PACKING_EFFICIENCY = Math.sqrt(.066666);
	
	/**
	 * The size, in cups, of each side of the triangle
	 */
	private static final int TRIANGLE_SIZE = 4;
	
	/**
	 * List of virtual cups
	 */
	private List<VirtualCup> cups;

	/**
	 * Constructor
	 */
	public TableGUI() {
		this.cups = new ArrayList<TableGUI.VirtualCup>();
		this.stackCups();
		this.addMouseListener(this);
		this.stackCups();
	}

	/**
	 * creates two stacks of cups and initializes them
	 */
	public void stackCups() {
		this.cups.clear();
		for (int column = 0; column < TRIANGLE_SIZE; column++) {
			for (int row = 0; row < TRIANGLE_SIZE - column; row++) {
				this.cups.add(new VirtualCup(column, row, "L:" + column + ":" + row));
				this.cups.add(new VirtualCup(TRIANGLE_SIZE * 2 - column, row
						- TRIANGLE_SIZE + column, "R:" + column + ":" + row));
			}
		}
	}
	
	@Override
	public void paint(Graphics g) {
		super.paint(g);
		Graphics2D g2d = (Graphics2D) g;
		// Enable antialiasing for text
		g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
				RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		// Enable antialiasing for shapes
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);

		for (VirtualCup cup : this.cups) {
			cup.paint(g2d);
		}
	}

	/**
	 * @author Don
	 * emulates a cup, capable of listening to the screen for size and render hints
	 *
	 */
	private class VirtualCup {
		int column, row, x, y, radius;
		Color curColor;
		String name;

		/**
		 * @param column
		 * the column in which this circle will draw
		 * @param row
		 * the row in which this circle will draw, shifted down by half a circle per column
		 * @param name
		 * the identification for this cup, as rendered
		 */
		public VirtualCup(int column, int row, String name) {
			this.row = row;
			this.column = column;
			this.curColor = Color.GREEN;
			this.name = name;
		}

		/**
		 * @param point
		 * @return
		 * if circle contains point
		 */
		public boolean contains(Point point) {
			int centerx = this.x + this.radius;
			int centery = this.y + this.radius;
			int xDif = point.x - centerx;
			int yDif = point.y - centery;
			return (xDif * xDif) + (yDif * yDif) < (this.radius * this.radius);
		}

		/**
		 * updates the values of x, y, and radius based on the screen size
		 */
		public void updateVariables(){
			this.radius = (int) (Math.min(TableGUI.this.getWidth() * .45,
					TableGUI.this.getHeight())
					/ TRIANGLE_SIZE / 2);
			this.x = this.column
					* this.radius
					* 2
					- (int) (this.radius * this.column * CIRCLE_PACKING_EFFICIENCY);
			this.y = this.row * this.radius * 2 + this.radius * this.column;
		}
		
		public void paint(Graphics2D g) {
			updateVariables();

			g.setStroke(new BasicStroke(this.radius / 15));
			
			g.setColor(this.curColor);
			g.fillOval(this.x, this.y, this.radius * 2, this.radius * 2);
			g.setColor(Color.BLACK);
			g.drawOval(this.x, this.y, this.radius * 2, this.radius * 2);
			g.setFont(new Font("", Font.BOLD, 16));
			Rectangle2D bounds = g.getFontMetrics().getStringBounds(this.name,
					g);
			g.drawString(this.name,
					(int) (this.x - bounds.getCenterX() + this.radius),
					(int) (this.y - bounds.getCenterY()) + this.radius);
		}

		/**
		 * Toggles a cup between 2 states, as shown by the color
		 */
		public void toggleCup() {
			if (this.curColor == Color.GREEN) {
				this.curColor = Color.RED;
			} else {
				this.curColor = Color.GREEN;
			}
		}
	}

	public static void main(String[] args) {
		JFrame jf = new JFrame();
		jf.add(new TableGUI());
		jf.setVisible(true);
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jf.setSize(500, 500);

	}
	
	@Override
	public void mouseClicked(MouseEvent arg0) {
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
	}

	@Override
	public void mousePressed(MouseEvent e) {
		for (VirtualCup cup : this.cups) {
			if (cup.contains(e.getPoint())) {
				// XXX reaction code goes here, toggle is place holder 
				cup.toggleCup();
			}
		}
		this.repaint();
	}
	
	@Override
	public void mouseReleased(MouseEvent arg0) {
	}
}
